import axios from 'axios'
import {t, message, bs} from "@/service/index.js"
import CryptoJS from 'crypto-js/crypto-js'
import duplicates from "@/service/duplicates.js";


const service = axios.create({
    baseURL: import.meta.env.ENV_BASE_URL,
    timeout: import.meta.env.ENV_TIMEOUT,
})

/**
 * AES加密 ：字符串 key iv  返回base64
 */
const encrypt = (word,ivStr) => {
    let key = CryptoJS.enc.Utf8.parse(bs().userKey);
    let iv = CryptoJS.enc.Utf8.parse(ivStr);
    let src = CryptoJS.enc.Utf8.parse(word);
    let encrypted = CryptoJS.AES.encrypt(src, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
    });
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}

/**
 * AES 解密 ：字符串 key iv  返回base64
 */
const decrypt = (word, ivStr) => {
    let key = CryptoJS.enc.Utf8.parse(bs().userKey);
    let iv = CryptoJS.enc.Utf8.parse(ivStr);
    let base64 = CryptoJS.enc.Base64.parse(word);
    let src = CryptoJS.enc.Base64.stringify(base64);
    let decrypt = CryptoJS.AES.decrypt(src, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
    });
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
}

const iv = () => {
    let result           = '';
    let characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let charactersLength = characters.length;
    for ( let i = 0; i < 16; i++ ) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

// 上传方法
service.upload = function(url, data, time = import.meta.env.ENV_TIMEOUT) {
    let fd = new FormData();
    Object.keys(data).forEach(key => {
        if(key === 'files'){
            let files = data[key]
            for (let i = 0; i < files.length; i++) {
                fd.append('file', files[i])
            }
            return
        }
        fd.append(key, data[key])
    })
    return service.request({
        url: url,
        data: fd,
        method: 'post',
        timeout: time,
        headers: {'upload': true},
    })
}


// 添加请求拦截器
service.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    let token = bs().token
    config.headers["token"] = token ? token : null
    config.headers["Accept-Language"] = bs().localState.name
    const iv = config.headers["iv"]
    config.data = iv ? encrypt(JSON.stringify(config.data),iv) : config.data
    if(config.headers["upload"]){
        config.headers["Content-Type"] = "multipart/form-data";
        return config;
    }
    duplicates.removePendingRequest(config)
    duplicates.addPendingRequest( config)
    return config;
}, function (error) {
    // 对请求错误做些什么
    message.error(t(`axios.${error.response.status}`))
    return Promise.reject({
        msg: error.message,
        code: error.response.status,
        data: null
    });
});

// 添加响应拦截器
service.interceptors.response.use(function (response) {
    duplicates.removePendingRequest(response.config)
    if(response.headers["content-type"].indexOf("application/json") === -1){
        return response
    }
    let data = response.data
    let iv = response.headers["iv"]
    data = iv ? JSON.parse(decrypt(data,iv)) : data
    // 未登录
    if (data.code === 401) {
        message.error(data.msg)
        bs().token = null
        location.reload()
        return Promise.reject(data);
    }
    // 请求错误
    if (data.code !== 200) {
        message.warning(data.msg)
        return Promise.reject(data);
    }
    return data;
}, function (error) {
    // 错误处理时也需要移除请求
    if (error.config) {
        duplicates.removePendingRequest(error.config)
    }
    if (axios.isCancel(error)) {
        console.log('请求被取消:', error.message)
        return
    }
    message.error(t(`axios.${error.response.status}`))
    return Promise.reject({
        msg: error.message,
        code: error.response.status,
        data: null
    });
});

// 返回二进制流
service.postStream = function(url,data,time = null){
    return service.request({
        method: 'post',
        url: url,
        data: data,
        responseType: 'blob',
        timeout: time ? time : import.meta.env.ENV_TIMEOUT,
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'blob'
        }
    })
}



service.postIV = function(url,data,time = import.meta.env.ENV_TIMEOUT){
    return service.request({
        method: 'post',
        url: url,
        data: data,
        timeout: time,
        headers: {
            'iv':iv(),
            'Content-Type': 'application/json'
        }
    })
}


export default service